package com.bb.blog.security.config;

import com.bb.blog.security.component.SubjectAttributeUserTokenConverter;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import java.security.KeyPair;

@Configuration
@RequiredArgsConstructor
public class TokenServiceConfig {
    @Value("${bb-cloud.security.jwt.enable}")
    boolean jwtEnabled = true;

    private final KeyPair keyPair;

    private final RedisConnectionFactory redisConnectionFactory;

    private final ClientDetailsService clientDetailsService;

    private final AuthenticationManager authenticationManager;

    @Bean("bbTokenService")
    public DefaultTokenServices defaultTokenServices(){
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setReuseRefreshToken(false);
        tokenServices.setClientDetailsService(clientDetailsService);
        if(jwtEnabled){
            tokenServices.setTokenEnhancer(accessTokenConverter());
        }

        tokenServices.setAuthenticationManager(authenticationManager);
        return tokenServices;
    }

    @Bean
    public TokenStore tokenStore(){
        TokenStore tokenStore;
        if(jwtEnabled){
            tokenStore = new JwtTokenStore(accessTokenConverter());
        }else{
            tokenStore = new RedisTokenStore(redisConnectionFactory);
        }
        return tokenStore;
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setKeyPair(this.keyPair);

        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(new SubjectAttributeUserTokenConverter());
        converter.setAccessTokenConverter(accessTokenConverter);

        return converter;
    }
}
